package com.xxjh.brs.sftp.factory;

import cn.hutool.extra.ssh.Sftp;
import com.xxjh.brs.sftp.common.utils.SftpConstantsUtil;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @author CHENCHEN
 * @title a
 * @company 新兴际华科技（天津）有限公司
 * @create 2024-07-04 15:42
 */
@Component
public class SftpClientFactory {

    // 最大连接数
    private static final int MaxTotal = 200;
    // 最小空闲连接数
    private static final int MinIdle = 20;
    // 最大等待时间
    private static final int MaxWaitMillis = 25000;

    @Autowired
    private SftpProperties sftpProperties;

    @Bean(name = "sftpClientPoolPull")
    public ObjectPool<Sftp> sftpClientPoolPull() {
        return getObjectPool(sftpProperties.getPullServer());
    }

    @Bean(name = "sftpClientPoolPush")
    public ObjectPool<Sftp> sftpClientPoolPush() {
        return getObjectPool(sftpProperties.getPushServer());
    }

    private ObjectPool<Sftp> getObjectPool(SftpProperties.SftpServer server){
        GenericObjectPoolConfig<Sftp> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(MaxTotal);
        config.setMinIdle(MinIdle);
        config.setMaxWaitMillis(MaxWaitMillis);
        return new GenericObjectPool<>(new SftpConnectionFactory(server), config);
    }

    // Sftp的连接工厂类
    private static class SftpConnectionFactory extends BasePooledObjectFactory<Sftp> {

        private final SftpProperties.SftpServer sftpServerConfig;

        public SftpConnectionFactory(SftpProperties.SftpServer serverConfig) {
            this.sftpServerConfig = serverConfig;
        }

        public boolean isConnected(Sftp sftp) {
            try {
                // 尝试列出根目录，如果成功则认为连接正常
                sftp.home();
                return true;
            } catch (Exception e) {
                // 出现异常，则认为连接已经断开
                return false;
            }
        }

        @Override
        public Sftp create() throws Exception {
            return SftpConstantsUtil.createClient(sftpServerConfig);
        }

        @Override
        public PooledObject<Sftp> wrap(Sftp sftp) {
            return new DefaultPooledObject<>(sftp);
        }

        @Override
        public boolean validateObject(PooledObject<Sftp> pooledObject) {
            Sftp sftp = pooledObject.getObject();
            try {
                // 检查连接是否有效
                return isConnected(sftp);
            } catch (Exception e) {
                return false;
            }
        }

        @Override
        public void destroyObject(PooledObject<Sftp> pooledObject) throws Exception {
            Sftp sftp = pooledObject.getObject();
            try {
                if(sftp != null){
                    sftp.close();
                }
            } finally {
                // 通常不需要额外的finally块，因为disconnect通常足够安全
            }
        }

        @Override
        public void activateObject(PooledObject<Sftp> pooledObject) throws Exception {
            // 在对象被激活时执行的操作
        }

        @Override
        public void passivateObject(PooledObject<Sftp> pooledObject) throws Exception {
            // 在对象被归还到池中之前执行的操作
        }
    }
}
